package org.jsola.hr.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.jsola.common.DateKit;
import org.jsola.core.Page;
import org.jsola.core.entity.BaseDO;
import org.jsola.exception.ParamException;
import org.jsola.hr.common.BigDecimalKit;
import org.jsola.hr.common.DateUtils;
import org.jsola.hr.common.ExampleKit;
import org.jsola.hr.constant.ConfigCodeConstants;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.dao.*;
import org.jsola.hr.dto.SalaryBillAddDTO;
import org.jsola.hr.dto.SalaryBillListDTO;
import org.jsola.hr.dto.SalaryBillUpdateDTO;
import org.jsola.hr.dto.excel.SalaryBillImportDTO;
import org.jsola.hr.entity.*;
import org.jsola.hr.provider.INoticeProviderService;
import org.jsola.hr.provider.ISiteConfigProviderService;
import org.jsola.hr.provider.IUserProviderService;
import org.jsola.hr.query.SalaryBillQuery;
import org.jsola.hr.service.*;
import org.jsola.hr.service.excel.SalaryBillImportListener;
import org.jsola.hr.vo.*;
import org.jsola.hr.vo.excel.ParseResultVO;
import org.jsola.user.core.TokenUser;
import org.jsola.user.entity.ThirdInfoDO;
import org.jsola.user.entity.UnionOpenIdDO;
import org.jsola.user.service.IThirdInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.io.File;
import java.math.BigDecimal;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 工资条
 *
 * @author zhr
 */
@Service("hrSalaryBillServiceImpl")
public class SalaryBillServiceImpl implements ISalaryBillService {

    @Value("${jsola.message.weixin.appid}")
    private String appId;

    @Autowired
    private ISalaryBillDAO salaryBillDAO;

    @Autowired
    private ISalaryBillFieldsDAO salaryBillFieldsDAO;

    @Autowired
    private ISalaryBillSendRelDAO salaryBillSendRelDAO;

    @Autowired
    private ISalaryTableDAO salaryTableDAO;

    @Autowired
    private IEmpInfoDAO empInfoDAO;

    @Autowired
    private ISalaryBillSendDAO salaryBillSendDAO;

    @Autowired
    private IDepInfoService depInfoService;

    @Autowired
    private IPositionInfoService positionInfoService;

    @Autowired
    private IThirdInfoService thirdInfoService;

    @Autowired
    private INoticeProviderService noticeProviderService;

    @Autowired
    private IUserProviderService userProviderService;

    @Autowired
    private IEmpInfoService empInfoService;

    @Autowired
    private INameVerifiedService nameVerifiedService;

    @Autowired
    private ISalaryBillSendRelService salaryBillSendRelService;

    @Autowired
    private ISiteConfigProviderService siteConfigProviderService;

    @Autowired
    private ISalaryTableService salaryTableService;

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public SalaryBillVO save(SalaryBillAddDTO salaryBillAddDTO, TokenUser tokenUser) {
        // 转DO
        SalaryBillDO salaryBillDO = salaryBillAddDTO.to(SalaryBillDO.class);
        // 保存
        salaryBillDO = save(salaryBillDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return salaryBillDO.to(SalaryBillVO.class);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public List<SalaryBillVO> batchSave(List<SalaryBillAddDTO> salaryBillAddDTOList, TokenUser tokenUser) {
        if (CollectionUtils.isEmpty(salaryBillAddDTOList)) {
            return null;
        }
        List<SalaryBillDO> salaryBillDOList = salaryBillAddDTOList
                .parallelStream()
                .map(salaryBillAddDTO -> {
                    SalaryBillDO salaryBillDO = salaryBillAddDTO.to(SalaryBillDO.class);
                    salaryBillDO.preInsert(tokenUser.getUserId());
                    salaryBillDO.setSiteId(tokenUser.getSiteId());
                    return salaryBillDO;
                }).collect(Collectors.toList());
        salaryBillDAO.insertListAndSetId(salaryBillDOList);
        return salaryBillDOList
                .parallelStream()
                .map(salaryBillDO -> salaryBillDO.to(SalaryBillVO.class))
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(SalaryBillUpdateDTO salaryBillUpdateDTO, TokenUser tokenUser) {
        //转DO
        SalaryBillDO salaryBillDO = salaryBillUpdateDTO.to(SalaryBillDO.class);
        //根据主键更新，只更新非null值

        //根据tableId查找工资条
        SalaryBillDO newSalaryBillDO = findTableId(salaryBillDO.getId(), tokenUser.getSiteId());
        ParamException.notNull(newSalaryBillDO, "工资条不存在，请刷新后重试");
        if (newSalaryBillDO.getCheckTime() == null) {
            Date checkTime = new Date();
            newSalaryBillDO.setCheckTime(checkTime);
            newSalaryBillDO.setCheckStatus(salaryBillUpdateDTO.getCheckStatus());
            // 工资条发放信息
            List<SalaryBillSendRelDO> salaryBillSendRelDOList
                    = salaryBillSendRelService.selectByBillId(newSalaryBillDO.getId(), tokenUser.getSiteId());
            // 同步修改发放状态
            for (SalaryBillSendRelDO salaryBillSendRelDO : salaryBillSendRelDOList) {
                salaryBillSendRelDO.setCheckStatus(salaryBillUpdateDTO.getCheckStatus());
                salaryBillSendRelService.updateByIdSelective(salaryBillSendRelDO, tokenUser.getSiteId(), tokenUser.getUserId());
            }
        }
        return updateByIdSelective(newSalaryBillDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, String... salaryBillIds) {
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) salaryBillIds);
    }


    @Override
    public SalaryBillVO selectById(String salaryBillId, TokenUser tokenUser) {
        SalaryBillDO salaryBillDO = selectDOById(salaryBillId, tokenUser.getSiteId());
        if (salaryBillDO == null) {
            return null;
        }
        SalaryBillDO update = new SalaryBillDO();
        update.setId(salaryBillId);
        update.setReadStatus(true);
        //根据主键更新，只更新非null值
        this.updateByIdSelective(salaryBillDO, tokenUser.getSiteId(), tokenUser.getUserId());

        SalaryBillDO newSalaryBillDO = selectDOById(salaryBillId, tokenUser.getSiteId());
        return newSalaryBillDO.to(SalaryBillVO.class);
    }

    @Override
    public List<SalaryBillVO> selectByIds(List<String> salaryBillIds, String siteId) {
        List<SalaryBillDO> salaryBillDOS = listByIds(siteId, salaryBillIds);
        return salaryBillDOS.stream().map(salaryBillDO -> salaryBillDO.to(SalaryBillVO.class)).collect(Collectors.toList());
    }

    @Override
    public List<SalaryBillListVO> select(SalaryBillQuery salaryBillQuery, String siteId) {
        List<SalaryBillDO> salaryBillDOList = selectDO(salaryBillQuery, siteId);
        if (CollectionUtils.isEmpty(salaryBillDOList)) {
            return salaryBillDOList == null ? null : new ArrayList<>();
        }
        return salaryBillDOList.stream()
                .map(salaryBillDO -> salaryBillDO.to(SalaryBillListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public int selectCount(SalaryBillQuery salaryBillQuery, String siteId) {
        Example example = buildExample(salaryBillQuery, siteId);
        return salaryBillDAO.selectCountByExample(example);
    }

    @Override
    public Page<SalaryBillListVO> selectPage(SalaryBillQuery salaryBillQuery, String siteId) {
        Example example = buildExample(salaryBillQuery, siteId);
        Page<SalaryBillDO> page = salaryBillDAO.selectPageByExample(example,
                salaryBillQuery.getPageNo(),
                salaryBillQuery.getPageSize());

        return page.to(SalaryBillListVO.class);
    }

    @Override
    public SalaryBillDO selectDOById(String salaryBillId, String siteId) {
        return listById(salaryBillId, siteId);
    }

    @Override
    public List<SalaryBillDO> selectDO(SalaryBillQuery salaryBillQuery, String siteId) {
        Example example = buildExample(salaryBillQuery, siteId);
        return salaryBillDAO.selectByExample(example);
    }


    @Override
    public List<ParseResultVO<SalaryBillImportDTO>> parseImportFile(File file, Boolean success, TokenUser tokenUser) {
        SalaryBillImportListener salaryBillImportListener = new SalaryBillImportListener();
        salaryBillImportListener.setTokenUser(tokenUser);
        salaryBillImportListener.setParseOnly(true);
        // 读取excel 只解析不入库
        EasyExcel.read(file, SalaryBillImportDTO.class, salaryBillImportListener).sheet().doRead();
        if (success == null) {
            return salaryBillImportListener.getParseResultList();
        } else {
            return salaryBillImportListener.getParseResultList()
                    .stream()
                    .filter(parseResult -> success.equals(parseResult.getSuccess()))
                    .collect(Collectors.toList());
        }
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public SalaryBillImportExcelVO importFile(File file, TokenUser tokenUser, Boolean force, String companyId, String year, String month, String tableName) {
        // 验证公司下同年月工资表名重复
        Example example = new Example(SalaryTableDO.class);
        example.and()
                .andEqualTo("companyId", companyId)
                .andEqualTo("year", year)
                .andEqualTo("month", month)
                .andEqualTo("tableName", tableName)
                .andEqualTo("valid", true);
        Integer tableNameCount = salaryTableDAO.selectCountByExample(example);
        if (tableNameCount > 0) {
            throw new ParamException("所选年月下已存在同名工资表");
        }

        SalaryBillImportListener salaryBillImportListener = new SalaryBillImportListener();
        salaryBillImportListener.setTokenUser(tokenUser);
        salaryBillImportListener.setForce(force);
        salaryBillImportListener.setCompanyId(companyId);
        salaryBillImportListener.setYear(year);
        salaryBillImportListener.setMonth(month);
        salaryBillImportListener.setTableName(tableName);
        // 读取excel 并且入库
        EasyExcel.read(file, SalaryBillImportDTO.class, salaryBillImportListener).sheet().doRead();
        return salaryBillImportListener.getSalaryBillImportExcelVO();
    }


    /**
     * 根据查询参数，构建example
     *
     * @param salaryBillQuery 查询参数
     * @param siteId          所属站点id
     * @return example
     */
    private Example buildExample(SalaryBillQuery salaryBillQuery, String siteId) {
        Example example = new Example(SalaryBillDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        if (salaryBillQuery.getTableId() != null) {
            example.and().andEqualTo("tableId", salaryBillQuery.getTableId());
        }
        if (salaryBillQuery.getEmpInCompany() != null) {
            example.and().andEqualTo("empInCompany", salaryBillQuery.getEmpInCompany());
        }
        if (salaryBillQuery.getEmpId() != null) {
            example.and().andEqualTo("empId", salaryBillQuery.getEmpId());
        }
        if (salaryBillQuery.getYear() != null) {
            example.and().andEqualTo("year", salaryBillQuery.getYear());
        }
        if (salaryBillQuery.getMonth() != null) {
            example.and().andEqualTo("month", salaryBillQuery.getMonth());
        }
        if (salaryBillQuery.getSalaryAmount() != null) {
            example.and().andEqualTo("salaryAmount", salaryBillQuery.getSalaryAmount());
        }
        if (salaryBillQuery.getSalaryReal() != null) {
            example.and().andEqualTo("salaryReal", salaryBillQuery.getSalaryReal());
        }
        if (salaryBillQuery.getSendType() != null) {
            example.and().andEqualTo("sendType", salaryBillQuery.getSendType());
        }
        if (salaryBillQuery.getSendStatus() != null) {
            example.and().andEqualTo("sendStatus", salaryBillQuery.getSendStatus());
        }
        if (salaryBillQuery.getReadStatus() != null) {
            example.and().andEqualTo("readStatus", salaryBillQuery.getReadStatus());
        }
        if (salaryBillQuery.getCheckStatus() != null) {
            example.and().andEqualTo("checkStatus", salaryBillQuery.getCheckStatus());
        }
        if (salaryBillQuery.getWithdrawnStatus() != null) {
            example.and().andEqualTo("withdrawnStatus", salaryBillQuery.getWithdrawnStatus());
        }
        if (salaryBillQuery.getSendTime() != null) {
            example.and().andEqualTo("sendTime", salaryBillQuery.getSendTime());
        }
        if (salaryBillQuery.getReadTime() != null) {
            example.and().andEqualTo("readTime", salaryBillQuery.getReadTime());
        }
        if (salaryBillQuery.getCheckTime() != null) {
            example.and().andEqualTo("checkTime", salaryBillQuery.getCheckTime());
        }
        if (salaryBillQuery.getWithdrawnTime() != null) {
            example.and().andEqualTo("withdrawnTime", salaryBillQuery.getWithdrawnTime());
        }
        if (salaryBillQuery.getPhoneStatus() != null) {
            example.and().andEqualTo("phoneStatus", salaryBillQuery.getPhoneStatus());
        }
        if (salaryBillQuery.getPhone() != null) {
            example.and().andEqualTo("phone", salaryBillQuery.getPhone());
        }
        if (salaryBillQuery.getEmpName() != null) {
            example.and().andEqualTo("empName", salaryBillQuery.getEmpName());
        }
        if (salaryBillQuery.getWechatStatus() != null) {
            example.and().andEqualTo("wechatStatus", salaryBillQuery.getWechatStatus());
        }
        if (salaryBillQuery.getEmpNo() != null) {
            example.and().andEqualTo("empNo", salaryBillQuery.getEmpNo());
        }
        if (salaryBillQuery.getDepId() != null) {
            example.and().andEqualTo("depId", salaryBillQuery.getDepId());
        }
        if (salaryBillQuery.getDepName() != null) {
            example.and().andEqualTo("depName", salaryBillQuery.getDepName());
        }
        if (salaryBillQuery.getPositionId() != null) {
            example.and().andEqualTo("positionId", salaryBillQuery.getPositionId());
        }
        if (salaryBillQuery.getPositionName() != null) {
            example.and().andEqualTo("positionName", salaryBillQuery.getPositionName());
        }
        if (salaryBillQuery.getSalaryBasic() != null) {
            example.and().andEqualTo("salaryBasic", salaryBillQuery.getSalaryBasic());
        }
        if (salaryBillQuery.getEmpSoc() != null) {
            example.and().andEqualTo("empSoc", salaryBillQuery.getEmpSoc());
        }
        if (salaryBillQuery.getEmpPf() != null) {
            example.and().andEqualTo("empPf", salaryBillQuery.getEmpPf());
        }
        if (salaryBillQuery.getEmpTax() != null) {
            example.and().andEqualTo("empTax", salaryBillQuery.getEmpTax());
        }
        if (salaryBillQuery.getCompanyId() != null) {
            example.and().andEqualTo("companyId", salaryBillQuery.getCompanyId());
        }
        if (salaryBillQuery.getSort() != null) {
            example.and().andEqualTo("sort", salaryBillQuery.getSort());
        }
        if (StringUtils.isNotBlank(salaryBillQuery.getNameOrPhone())) {
            example.and()
                    .orLike("empName", "%" + salaryBillQuery.getNameOrPhone() + "%")
                    .orLike("phone", "%" + salaryBillQuery.getNameOrPhone() + "%");
        }
        // 排序
        ExampleKit.setExampleOrder(example, salaryBillQuery.getOrders());
        return example;
    }

    @Override
    public SalaryBillImportExcelVO saveExcelDataList(List<SalaryBillImportDTO> list, TokenUser tokenUser, String companyId, String year, String month, String tableName, Map<Integer, String> headMap) {

        SalaryBillImportExcelVO salaryBillImportExcelVO = new SalaryBillImportExcelVO();
        //成功导入列表
        List<SalaryBillImportRecordVO> importSucList = new ArrayList<>();
        //失败导入列表
        List<SalaryBillImportRecordVO> importFailList = new ArrayList<>();
        //保存工资条列表
        List<SalaryBillDO> salaryBillDOList = new ArrayList<>();

        //新增工资表记录
        SalaryTableDO salaryTableDO = new SalaryTableDO();
        salaryTableDO.setCompanyId(companyId);
        salaryTableDO.setTableName(tableName);
        salaryTableDO.setYear(year);
        salaryTableDO.setMonth(month);
        salaryTableDO.preInsert(tokenUser.getUserId());
        salaryTableDO.setSiteId(tokenUser.getSiteId());
        String headerListString = headMap.values().stream().filter(name -> !"员工姓名".equals(name)
                && !"手机号".equals(name)).collect(Collectors.joining(","));
        salaryTableDO.setHeaderListString(headerListString);
        salaryTableDAO.insertSelective(salaryTableDO);
        salaryBillImportExcelVO.setTableId(salaryTableDO.getId());

        // 工资条排序字段
        int billSort = 1;
        // 已导入手机号列表
        List<String> phoneImportedList = new ArrayList<>();

        // 遍历获取表名对应的序号
        Map<String, Integer> headSortMap = new HashMap<>();
        headMap.forEach((code, value) -> {
            headSortMap.put(value, code);
        });

        List<String> expList = new ArrayList<>();
        expList.add("手机号");
        expList.add("员工姓名");
        expList.add("应发工资");
        expList.add("实发工资");
        expList.add("部门名称");
        expList.add("岗位名称");
        expList.add("基本工资");
        expList.add("个人社保");
        expList.add("个人公积金");
        expList.add("个人所得税");
        expList.add("考勤扣款");

        Map<String, Integer> otherSortMap = new HashMap<>();
        // 剩余的属性
        headSortMap.forEach((code, value) -> {
            if (!expList.contains(code)) {
                otherSortMap.put(code, value);
            }
        });


        for (SalaryBillImportDTO salaryBillImportDTO : list) {
            SalaryBillImportRecordVO salaryBillImportRecordVO = new SalaryBillImportRecordVO();
            salaryBillImportRecordVO.setId(salaryBillImportDTO.getId());
            int phoneNum = headSortMap.get("手机号");
            int nameNum = headSortMap.get("员工姓名");
            int yfNum = headSortMap.get("应发工资");
            int sfNum = headSortMap.get("实发工资");
            if ("以下提示可删除：".equals(salaryBillImportDTO.getBase0())) {
                break;
            }
            JSONObject salaryObj = JSONObject.parseObject(JSON.toJSONString(salaryBillImportDTO));

            String phone = !salaryObj.containsKey("base" + phoneNum) ? "" : salaryObj.getString("base" + phoneNum);
            String empName = !salaryObj.containsKey("base" + nameNum) ? "" : salaryObj.getString("base" + nameNum);

            //验证手机号和员工姓名不可为空
            if (!salaryObj.containsKey("base" + phoneNum) || !salaryObj.containsKey("base" + nameNum) ||
                    !salaryObj.containsKey("base" + yfNum) || !salaryObj.containsKey("base" + sfNum)) {
                salaryBillImportRecordVO.setName(empName);
                salaryBillImportRecordVO.setPhone(phone);
                salaryBillImportRecordVO.setStatus(0);
                salaryBillImportRecordVO.setReason("导入工资条（手机号、姓名、应发工资、实发工资）不可为空，请检查导入文件数据完整性");
                importFailList.add(salaryBillImportRecordVO);
                continue;
            }

            String yf = salaryObj.getString("base" + yfNum);
            String sf = salaryObj.getString("base" + sfNum);

            //验证手机号格式
            String phoneRegex = "^[1][3,4,5,6,7,8,9][0-9]{9}$";
            Pattern p = Pattern.compile(phoneRegex);
            Matcher m = p.matcher(phone);
            if (!m.matches()) {
                salaryBillImportRecordVO.setName(empName);
                salaryBillImportRecordVO.setPhone(phone);
                salaryBillImportRecordVO.setStatus(0);
                salaryBillImportRecordVO.setReason("手机号：【" + phone + "】格式不正确");
                importFailList.add(salaryBillImportRecordVO);
                continue;
            }

            //验证手机号导入重复
            if (phoneImportedList.contains(phone)) {
                salaryBillImportRecordVO.setName(empName);
                salaryBillImportRecordVO.setPhone(phone);
                salaryBillImportRecordVO.setStatus(0);
                salaryBillImportRecordVO.setReason("手机号：【" + phone + "】已导入过，不可重复导入");
                importFailList.add(salaryBillImportRecordVO);
                continue;
            }

            //处理工资条参数
            SalaryBillDO salaryBillDO = salaryBillImportDTO.to(SalaryBillDO.class);
            salaryBillDO.setTableId(salaryTableDO.getId());
            if (salaryBillDO.getSendStatus() == null) {
                // 发送状态（0：未发送，1：已发送）
                salaryBillDO.setSendStatus(false);
            }
            if (salaryBillDO.getReadStatus() == null) {
                // 查看状态（0：未查看，1：已查看）
                salaryBillDO.setReadStatus(false);
            }
            if (salaryBillDO.getCheckStatus() == null) {
                // 确认状态（0：未确认，1：已确认，2：有异议）
                salaryBillDO.setCheckStatus(false);
            }
            if (salaryBillDO.getWithdrawnStatus() == null) {
                // 撤回状态（0：未撤回，1：已撤回）
                salaryBillDO.setWithdrawnStatus(false);
            }
            if (salaryBillDO.getPhoneStatus() == null) {
                // 是否包含手机号（0：否，1：是）
                salaryBillDO.setPhoneStatus(true);
            }
            //部门
            if (headSortMap.containsKey("部门名称")) {
                int num = headSortMap.get("部门名称");
                if (salaryObj.containsKey("base" + num)) {
                    String depName = salaryObj.getString("base" + num);
                    List<DepInfoDO> depInfoList = depInfoService.listByName(depName, companyId, tokenUser.getSiteId());
                    if (!CollectionUtils.isEmpty(depInfoList)) {
                        salaryBillDO.setDepId(depInfoList.get(0).getId());
                        salaryBillDO.setDepName(depInfoList.get(0).getName());
                    }
                }
            }

            //岗位
            if (headSortMap.containsKey("岗位名称")) {
                int num = headSortMap.get("岗位名称");
                if (salaryObj.containsKey("base" + num)) {
                    String positionName = salaryObj.getString("base" + num);
                    List<PositionInfoDO> positionInfoList = positionInfoService.listByName(positionName, companyId, tokenUser.getSiteId());
                    if (!CollectionUtils.isEmpty(positionInfoList)) {
                        salaryBillDO.setPositionId(positionInfoList.get(0).getId());
                        salaryBillDO.setPositionName(positionInfoList.get(0).getName());
                    }
                }
            }
            // 默认设置未绑定微信
            salaryBillDO.setWechatStatus(false);
            // 年份
            salaryBillDO.setYear(year);
            // 月份
            salaryBillDO.setMonth(month);

            salaryBillDO.setSalaryAmount(stringToBig(yf));
            salaryBillDO.setSalaryReal(stringToBig(sf));
            salaryBillDO.setPhone(phone);
            salaryBillDO.setEmpName(empName);

            // 基本工资
            if (headSortMap.containsKey("基本工资")) {
                int num = headSortMap.get("基本工资");
                if (salaryObj.containsKey("base" + num)) {
                    String value = salaryObj.getString("base" + num);
                    salaryBillDO.setSalaryBasic(stringToBig(value));
                }
            }
            // 个人社保
            if (headSortMap.containsKey("个人社保")) {
                int num = headSortMap.get("个人社保");
                if (salaryObj.containsKey("base" + num)) {
                    String value = salaryObj.getString("base" + num);
                    salaryBillDO.setEmpSoc(stringToBig(value));
                }
            }
            // 个人公积金
            if (headSortMap.containsKey("个人公积金")) {
                int num = headSortMap.get("个人公积金");
                if (salaryObj.containsKey("base" + num)) {
                    String value = salaryObj.getString("base" + num);
                    salaryBillDO.setEmpPf(stringToBig(value));
                }
            }
            // 个人所得税
            if (headSortMap.containsKey("个人所得税")) {
                int num = headSortMap.get("个人所得税");
                if (salaryObj.containsKey("base" + num)) {
                    String value = salaryObj.getString("base" + num);
                    salaryBillDO.setEmpTax(stringToBig(value));
                }
            }
            // 考勤扣款
            if (headSortMap.containsKey("考勤扣款")) {
                int num = headSortMap.get("考勤扣款");
                if (salaryObj.containsKey("base" + num)) {
                    String value = salaryObj.getString("base" + num);
                    salaryBillDO.setDeduction(stringToBig(value));
                }
            }

            // 是否企业员工（0：否，1：是）
            EmpInfoVO empInfoVO = empInfoService.selectByPhone(companyId, salaryBillDO.getPhone(), tokenUser.getSiteId());
            if (Objects.nonNull(empInfoVO)) {
                // 是企业员工
                salaryBillDO.setEmpInCompany(true);
                // 员工ID
                salaryBillDO.setEmpId(empInfoVO.getId());
                // 工号
                salaryBillDO.setEmpNo(empInfoVO.getNumber());
                // 是否开通微信
                UnionOpenIdDO unionOpenIdDO = userProviderService.getUnionOpenByUserId(appId, empInfoVO.getUserId());
                if (Objects.nonNull(unionOpenIdDO)) {
                    // 已绑定微信
                    salaryBillDO.setWechatStatus(true);
                }
            } else {
                // 非企业员工
                salaryBillDO.setEmpInCompany(false);
                // 默认设置未绑定微信
                salaryBillDO.setWechatStatus(false);
            }

            // 通用字段
            salaryBillDO.setCompanyId(companyId);
            salaryBillDO.setSort(billSort++);
            salaryBillDO.preInsert(tokenUser.getUserId());
            salaryBillDO.setSiteId(tokenUser.getSiteId());

            // 自定义表头扩展字段
            List<SalaryBillFieldsDO> salaryBillFieldsDOList = new ArrayList<>();

            otherSortMap.forEach((code, num) -> {
                String value = salaryObj.getString("base" + num);
                SalaryBillFieldsDO salaryBillFieldsDO = new SalaryBillFieldsDO();

                salaryBillFieldsDO.setFieldName(code);
                salaryBillFieldsDO.setFieldValue(value);
                salaryBillFieldsDO.setNeedCalculate(false);
                salaryBillFieldsDO.setSort(num);
                salaryBillFieldsDOList.add(salaryBillFieldsDO);
            });
            salaryBillDO.setSalaryBillFieldsDOList(salaryBillFieldsDOList);
            salaryBillDO.setId(null);
            salaryBillDOList.add(salaryBillDO);
            salaryBillImportRecordVO.setStatus(1);
            salaryBillImportRecordVO.setReason("导入成功");
            salaryBillImportRecordVO.setName(salaryBillDO.getEmpName());
            salaryBillImportRecordVO.setPhone(salaryBillDO.getPhone());
            importSucList.add(salaryBillImportRecordVO);

            //将手机号添加到已导入列表中
            phoneImportedList.add(phone);
        }

        if (!CollectionUtils.isEmpty(salaryBillDOList)) {
            // 批量保存
            salaryBillDAO.insertListAndSetId(salaryBillDOList);
            // 批量保存自定义表头字段
            List<SalaryBillFieldsDO> salaryBillFieldsList = new ArrayList<>();
            salaryBillDOList.forEach(item -> {
                if (!CollectionUtils.isEmpty(item.getSalaryBillFieldsDOList())) {
                    item.getSalaryBillFieldsDOList().forEach(itemChild -> {
                        itemChild.setBillId(item.getId());
                        itemChild.setSiteId(tokenUser.getSiteId());
                        salaryBillFieldsList.add(itemChild);
                    });
                }
            });
            if (!CollectionUtils.isEmpty(salaryBillFieldsList)) {
                salaryBillFieldsDAO.insertListAndSetId(salaryBillFieldsList);
            }
        }

        salaryBillImportExcelVO.setImportAllList(new ArrayList<>());
        salaryBillImportExcelVO.setImportSucList(importSucList);
        salaryBillImportExcelVO.setImportFailList(importFailList);

        return salaryBillImportExcelVO;
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public String autoGenerateSalaryBill(String companyId, String yearly, String monthly, String tableName
            , List<AutoGenerateSalaryBillVO> salaryBillList, String headerListString, TokenUser tokenUser) {
        //新增工资表记录
        SalaryTableDO salaryTableDO = new SalaryTableDO();
        salaryTableDO.setCompanyId(companyId);
        salaryTableDO.setTableName(tableName);
        salaryTableDO.setYear(yearly);
        salaryTableDO.setMonth(monthly);
        salaryTableDO.setHeaderListString(headerListString);
        salaryTableDO.preInsert(tokenUser.getUserId());
        salaryTableDO.setSiteId(tokenUser.getSiteId());
        salaryTableDAO.insertSelective(salaryTableDO);
        // 工资条排序字段
        int billSort = 1;
        // 月工资表id
        String tableDOId = salaryTableDO.getId();

        //保存工资条列表
        List<SalaryBillDO> saveSalaryBillDOList = new ArrayList<>();
        for (AutoGenerateSalaryBillVO salaryBillVO : salaryBillList) {
            // 个人社保
            BigDecimal empSoc = salaryBillVO.getEmpSoc();
            // 个人公积金
            BigDecimal empPf = salaryBillVO.getEmpPf();
            // 个人所得税
            BigDecimal empTax = salaryBillVO.getEmpTax();
            // 基本工资
            BigDecimal salaryBasic = salaryBillVO.getSalaryBasic();
            // 考勤扣款
            BigDecimal deduction = salaryBillVO.getDeduction();

            //处理工资条参数
            SalaryBillDO salaryBillDO = salaryBillVO.to(SalaryBillDO.class);
            salaryBillDO.setCompanyId(companyId);
            salaryBillDO.setTableId(tableDOId);

            // 发送状态（0：未发送，1：已发送）
            salaryBillDO.setSendStatus(false);
            // 查看状态（0：未查看，1：已查看）
            salaryBillDO.setReadStatus(false);
            // 确认状态（0：未确认，1：已确认，2：有异议）
            salaryBillDO.setCheckStatus(false);
            // 撤回状态（0：未撤回，1：已撤回）
            salaryBillDO.setWithdrawnStatus(false);
            // 是否包含手机号（0：否，1：是）
            salaryBillDO.setPhoneStatus(true);
            // 默认设置未绑定微信
            salaryBillDO.setWechatStatus(false);
            // 年份
            salaryBillDO.setYear(yearly);
            // 月份
            salaryBillDO.setMonth(monthly);
            // 基本工资
            salaryBillDO.setSalaryBasic(salaryBasic);
            // 个人社保
            salaryBillDO.setEmpSoc(empSoc);
            // 个人公积金
            salaryBillDO.setEmpPf(empPf);
            // 个人所得税
            salaryBillDO.setEmpTax(empTax);
            // 考勤扣款
            salaryBillDO.setDeduction(deduction);

            // 是否企业员工（0：否，1：是）
            Example example = new Example(EmpInfoDO.class);
            example.and()
                    .andEqualTo("id", salaryBillVO.getEmpId())
                    .andEqualTo("siteId", tokenUser.getSiteId())
                    .andEqualTo("valid", true);
            EmpInfoDO empInfoDO = empInfoDAO.selectOneByExample(example);
            if (Objects.nonNull(empInfoDO)) {
                salaryBillDO.setEmpName(empInfoDO.getName());
                salaryBillDO.setPhone(empInfoDO.getPhone());
                // 是企业员工
                salaryBillDO.setEmpInCompany(true);
                // 员工ID
                salaryBillDO.setEmpId(empInfoDO.getId());
                // 工号
                salaryBillDO.setEmpNo(empInfoDO.getNumber());
                // 是否开通微信
                if (StringUtils.isNotBlank(empInfoDO.getUnionId())) {
                    ThirdInfoDO thirdInfoDO = thirdInfoService.selectByUnionId(empInfoDO.getUnionId());
                    if (Objects.nonNull(thirdInfoDO) && StringUtils.isNotBlank(thirdInfoDO.getUserId())) {
                        // 已绑定微信
                        salaryBillDO.setWechatStatus(true);
                    }
                }
            } else {
                // 非企业员工
                salaryBillDO.setEmpInCompany(false);
                // 默认设置未绑定微信
                salaryBillDO.setWechatStatus(false);
            }
            // 通用字段
            salaryBillDO.setCompanyId(companyId);
            salaryBillDO.setSort(billSort++);
            salaryBillDO.preInsert(tokenUser.getUserId());
            salaryBillDO.setSiteId(tokenUser.getSiteId());

            // 自定义表头扩展字段
            List<SalaryBillFieldsDO> salaryBillFieldsDOList = salaryBillVO.getSalaryBillFieldsDOList();
            for (int i = 0; i < salaryBillFieldsDOList.size(); i++) {
                salaryBillFieldsDOList.get(i).setSort(i);
            }
            salaryBillDO.setId(null);
            saveSalaryBillDOList.add(salaryBillDO);
        }
        int count = 0;
        if (!CollectionUtils.isEmpty(saveSalaryBillDOList)) {
            // 批量保存
            count = salaryBillDAO.insertListAndSetId(saveSalaryBillDOList);
            // 批量保存自定义表头字段
            List<SalaryBillFieldsDO> salaryBillFieldsList = new ArrayList<>();
            saveSalaryBillDOList.forEach(item -> {
                if (!CollectionUtils.isEmpty(item.getSalaryBillFieldsDOList())) {
                    item.getSalaryBillFieldsDOList().forEach(itemChild -> {
                        itemChild.setBillId(item.getId());
                        itemChild.setSiteId(tokenUser.getSiteId());
                        salaryBillFieldsList.add(itemChild);
                    });
                }
            });
            if (!CollectionUtils.isEmpty(salaryBillFieldsList)) {
                salaryBillFieldsDAO.insertListAndSetId(salaryBillFieldsList);
            }
        }
        return tableDOId;
    }

    private BigDecimal stringToBig(String info) {
        BigDecimal bd = new BigDecimal(info);
        //设置小数位数，第一个变量是小数位数，第二个变量是取舍方法(四舍五入)
        bd = bd.setScale(2, BigDecimal.ROUND_HALF_UP);

        return bd;
    }

    @Override
    public SalaryBillListRelationVO pageRelation(SalaryBillQuery salaryBillQuery, String siteId) {
        SalaryBillListRelationVO salaryBillListRelationVO = new SalaryBillListRelationVO();
        // 查询工资条列表分页
        Example example = buildExample(salaryBillQuery, siteId);
        example.orderBy("sort").asc();
        Page<SalaryBillDO> page = salaryBillDAO.selectPageByExample(example,
                salaryBillQuery.getPageNo(),
                salaryBillQuery.getPageSize());

        SalaryBillListRelationVO newVO = selectSalaryBillListCount(salaryBillQuery, siteId);
        // 查询工资条相关统计
        if (salaryBillQuery.getReloadCount()) {
            salaryBillListRelationVO = newVO;
        }
        List<SalaryBillDO> salaryBillDOList = page.getEntities();
        // 查询工资条自定义字段列表
        if (!CollectionUtils.isEmpty(salaryBillDOList)) {
            setWechatStatus(salaryBillDOList);
            List<String> billIdList = salaryBillDOList.parallelStream().map(BaseDO::getId).collect(Collectors.toList());
            Example exampleField = new Example(SalaryBillFieldsDO.class);
            exampleField.and().andIn("billId", billIdList);
            exampleField.orderBy("sort").asc();
            List<SalaryBillFieldsDO> salaryBillFieldsDOList = salaryBillFieldsDAO.selectByExample(exampleField);
            // 关注公众号的员工Id
            List<String> weChatBindEmpIds = newVO.getWeChatBindEmpIds();
            // 工资表
            Object[] tableIds = salaryBillDOList.parallelStream().map(SalaryBillDO::getTableId)
                    .filter(Objects::nonNull).toArray(Object[]::new);
            List<SalaryTableDO> salaryTableDOList = salaryTableService.listByIds(siteId, tableIds);
            // 工资表-表头
            Map<String, String> tableIdHeaderListStringMap = salaryTableDOList.parallelStream()
                    .collect(Collectors.toMap(BaseDO::getId, SalaryTableDO::getHeaderListString));
            // 返回到列表中
            salaryBillDOList.forEach(salaryBillDO -> {
                List<SalaryBillFieldsDO> salaryBillFieldsDOListTmp = salaryBillFieldsDOList.parallelStream().map(itemChild -> {
                    if (salaryBillDO.getId().equals(itemChild.getBillId())) {
                        // 备注放在最后
                        if ("备注".equals(itemChild.getFieldName())) {
                            itemChild.setSort(10000);
                        }
                        if (itemChild.getSort() == null) {
                            // 没有排序的放中间
                            itemChild.setSort(5000);
                        }
                        return itemChild;
                    }
                    return null;
                }).filter(Objects::nonNull).collect(Collectors.toList());
                String headerListString = tableIdHeaderListStringMap.get(salaryBillDO.getTableId());
                if (StringUtils.isNotBlank(headerListString)) {
                    if (headerListString.contains("个人社保")) {
                        SalaryBillFieldsDO salaryBillFieldsDO = new SalaryBillFieldsDO();
                        salaryBillFieldsDO.setBillId(salaryBillDO.getId());
                        salaryBillFieldsDO.setFieldName("个人社保");
                        salaryBillFieldsDO.setFieldValue(salaryBillDO.getEmpSoc().stripTrailingZeros().toPlainString());
                        salaryBillFieldsDO.setNeedCalculate(Boolean.FALSE);
                        salaryBillFieldsDO.setSort(9997);
                        salaryBillFieldsDOListTmp.add(salaryBillFieldsDO);
                    }
                    if (headerListString.contains("个人公积金")) {
                        SalaryBillFieldsDO salaryBillFieldsDO = new SalaryBillFieldsDO();
                        salaryBillFieldsDO.setBillId(salaryBillDO.getId());
                        salaryBillFieldsDO.setFieldName("个人公积金");
                        salaryBillFieldsDO.setFieldValue(salaryBillDO.getEmpPf().stripTrailingZeros().toPlainString());
                        salaryBillFieldsDO.setNeedCalculate(Boolean.FALSE);
                        salaryBillFieldsDO.setSort(9998);
                        salaryBillFieldsDOListTmp.add(salaryBillFieldsDO);
                    }
                    if (headerListString.contains("个人所得税")) {
                        SalaryBillFieldsDO salaryBillFieldsDO = new SalaryBillFieldsDO();
                        salaryBillFieldsDO.setBillId(salaryBillDO.getId());
                        salaryBillFieldsDO.setFieldName("个人所得税");
                        salaryBillFieldsDO.setFieldValue(salaryBillDO.getEmpTax().stripTrailingZeros().toPlainString());
                        salaryBillFieldsDO.setNeedCalculate(Boolean.FALSE);
                        salaryBillFieldsDO.setSort(9999);
                        salaryBillFieldsDOListTmp.add(salaryBillFieldsDO);
                    }
                }
                salaryBillFieldsDOListTmp = salaryBillFieldsDOListTmp.parallelStream()
                        .sorted(Comparator.comparing(SalaryBillFieldsDO::getSort)).collect(Collectors.toList());
                salaryBillDO.setSalaryBillFieldsDOList(salaryBillFieldsDOListTmp);
                // 是否关注公众号
                if (CollectionUtils.isEmpty(weChatBindEmpIds) || !weChatBindEmpIds.contains(salaryBillDO.getEmpId())) {
                    salaryBillDO.setWechatStatus(Boolean.FALSE);
                } else {
                    salaryBillDO.setWechatStatus(Boolean.TRUE);
                }
            });
        }
        salaryBillListRelationVO.setSalaryBillListVOPage(page.to(SalaryBillListVO.class));

        return salaryBillListRelationVO;
    }

    /**
     * 电子工资条统计
     *
     * @param salaryBillQuery 查询条件
     * @param siteId          站点Id
     * @return 统计结果
     */
    private SalaryBillListRelationVO selectSalaryBillListCount(SalaryBillQuery salaryBillQuery, String siteId) {
        SalaryBillListRelationVO salaryBillListRelationVO = new SalaryBillListRelationVO();
        // 查询工资条相关统计
        List<SalaryBillListDTO> salaryBillListDTOList = salaryBillDAO.selectSalaryBillListCount(salaryBillQuery);
        if (CollectionUtils.isEmpty(salaryBillListDTOList)) {
            salaryBillListRelationVO.setCountAll(0);
            salaryBillListRelationVO.setCountInCompany(0);
            salaryBillListRelationVO.setCountNotInCompany(0);
            salaryBillListRelationVO.setCountWeChatBind(0);
            salaryBillListRelationVO.setCountWeChatUnBind(0);
            salaryBillListRelationVO.setSumSalaryAmount(BigDecimal.ZERO);
            salaryBillListRelationVO.setSumSalaryReal(BigDecimal.ZERO);
            salaryBillListRelationVO.setCountWeChatUnBind(0);
            return salaryBillListRelationVO;
        }
        // appId
        String appid = siteConfigProviderService.selectValueByCode(ConfigCodeConstants.CODE_APPID, siteId);
        Map<String, List<SalaryBillListDTO>> empListMap = salaryBillListDTOList.parallelStream()
                .filter(salaryBillListDTO -> salaryBillListDTO.getEmpId() != null)
                .collect(Collectors.groupingBy(SalaryBillListDTO::getEmpId));
        int countAll = empListMap.keySet().size();
        salaryBillListRelationVO.setCountAll(countAll);
        int countInCompany = 0;
        int countWeChatBind = 0;
        List<String> weChatBindEmpIds = new ArrayList<>();
        BigDecimal sumSalaryAmount = BigDecimal.ZERO;
        BigDecimal sumSalaryReal = BigDecimal.ZERO;
        for (String empId : empListMap.keySet()) {
            // 每个员工的数据 若关注了多个公众号就有多条数据
            List<SalaryBillListDTO> salaryBillList = empListMap.get(empId);
            boolean empInCompany = salaryBillList.parallelStream().anyMatch(SalaryBillListDTO::getEmpInCompany);
            if (empInCompany) {
                countInCompany++;
            }
            boolean anyMatch = salaryBillList.parallelStream().anyMatch(salaryBillListDTO
                    -> appid != null && appid.equals(salaryBillListDTO.getAppId()));
            if (anyMatch) {
                countWeChatBind++;
                weChatBindEmpIds.add(empId);
            }
            sumSalaryAmount = sumSalaryAmount.add(BigDecimalKit.nullToZero(salaryBillList.get(0).getSalaryAmount()));
            sumSalaryReal = sumSalaryReal.add(BigDecimalKit.nullToZero(salaryBillList.get(0).getSalaryReal()));
        }
        salaryBillListRelationVO.setCountInCompany(countInCompany);
        salaryBillListRelationVO.setCountNotInCompany(countAll - countInCompany);
        salaryBillListRelationVO.setSumSalaryAmount(sumSalaryAmount);
        salaryBillListRelationVO.setSumSalaryReal(sumSalaryReal);
        salaryBillListRelationVO.setCountWeChatBind(countWeChatBind);
        salaryBillListRelationVO.setCountWeChatUnBind(countAll - countWeChatBind);
        salaryBillListRelationVO.setWeChatBindEmpIds(weChatBindEmpIds);
        return salaryBillListRelationVO;
    }

    @Override
    public SalaryBillListRelationVO listAllRelation(SalaryBillQuery salaryBillQuery, String siteId) {
        SalaryBillListRelationVO salaryBillListRelationVO = new SalaryBillListRelationVO();
        SalaryBillListRelationVO newVO = selectSalaryBillListCount(salaryBillQuery, siteId);
        // 查询工资条相关统计
        if (salaryBillQuery.getReloadCount()) {
            salaryBillListRelationVO = newVO;
        }
        // 关注公众号的员工Id
        List<String> weChatBindEmpIds = newVO.getWeChatBindEmpIds();
        // 查询工资条列表分页
        Example example = buildExample(salaryBillQuery, siteId);
        example.orderBy("sort").asc();
        List<SalaryBillDO> salaryBillDOList = salaryBillDAO.selectByExample(example);
        salaryBillDOList = CollectionUtils.isEmpty(salaryBillDOList) ? new ArrayList<>() : salaryBillDOList;
        setWechatStatus(salaryBillDOList);
        List<SalaryBillListVO> salaryBillListVOList = salaryBillDOList.stream().map(item -> item.to(SalaryBillListVO.class)).collect(Collectors.toList());
        // 查询工资条自定义字段列表
        if (!CollectionUtils.isEmpty(salaryBillListVOList)) {
            List<String> billIdList = salaryBillListVOList.stream().map(SalaryBillListVO::getId).collect(Collectors.toList());
            Example exampleField = new Example(SalaryBillFieldsDO.class);
            exampleField.and().andIn("billId", billIdList);
            exampleField.orderBy("sort").asc();
            List<SalaryBillFieldsDO> salaryBillFieldsDOList = salaryBillFieldsDAO.selectByExample(exampleField);
            // 返回到列表中
            salaryBillListVOList.forEach(salaryBillDO -> {
                List<SalaryBillFieldsDO> salaryBillFieldsDOListTmp = new ArrayList<>();
                salaryBillFieldsDOList.forEach(itemChild -> {
                    if (salaryBillDO.getId().equals(itemChild.getBillId())) {
                        salaryBillFieldsDOListTmp.add(itemChild);
                    }
                });
                // 是否关注公众号
                if (CollectionUtils.isEmpty(weChatBindEmpIds) || !weChatBindEmpIds.contains(salaryBillDO.getEmpId())) {
                    salaryBillDO.setWechatStatus(Boolean.FALSE);
                } else {
                    salaryBillDO.setWechatStatus(Boolean.TRUE);
                }
                salaryBillDO.setSalaryBillFieldsDOList(salaryBillFieldsDOListTmp);
            });
        }
        salaryBillListRelationVO.setSalaryBillListVOList(salaryBillListVOList);

        return salaryBillListRelationVO;
    }


    /**
     * 设置微信绑定状态
     *
     * @param salaryBillDOList 工资条信息
     */
    private void setWechatStatus(List<SalaryBillDO> salaryBillDOList) {
        // 员工Ids
        List<String> empIds = salaryBillDOList.parallelStream().map(SalaryBillDO::getEmpId).collect(Collectors.toList());
        List<EmpInfoDO> empInfoDOList = empInfoService.selectDoByIds(empIds);
        // 员工-用户map
        Map<String, String> empUserIdMap = empInfoDOList.parallelStream().filter(empInfoDO -> empInfoDO.getUserId() != null)
                .collect(Collectors.toMap(BaseDO::getId, EmpInfoDO::getUserId));
        List<String> userIds = empUserIdMap.values().stream().distinct().collect(Collectors.toList());
        // 查询微信绑定情况
        List<ThirdInfoDO> thirdInfoDOList = userProviderService.selectUserSettingByIds(userIds);
        List<String> hadUserIds = thirdInfoDOList.parallelStream()
                .map(ThirdInfoDO::getUserId).distinct().collect(Collectors.toList());
        salaryBillDOList.parallelStream().forEach(salaryBillDO -> {
            salaryBillDO.setWechatStatus(salaryBillDO.getEmpId() != null && empUserIdMap.get(salaryBillDO.getEmpId())
                    != null && hadUserIds.contains(empUserIdMap.get(salaryBillDO.getEmpId())));
        });
    }

    @Override
    public SalaryBillVO getSalaryBillRelation(SalaryBillUpdateDTO salaryBillUpdateDTO, String siteId) {
        // 工资条信息
        SalaryBillDO salaryBillDO = salaryBillDAO.selectByPrimaryKey(salaryBillUpdateDTO.getId());

        // 工资条自定义字段
        Example exampleField = new Example(SalaryBillFieldsDO.class);
        exampleField.and().andEqualTo("billId", salaryBillDO.getId());
        List<SalaryBillFieldsDO> salaryBillFieldsDOList = salaryBillFieldsDAO.selectByExample(exampleField);
        salaryBillFieldsDOList = salaryBillFieldsDOList.stream()
                .sorted(Comparator.comparing(SalaryBillFieldsDO::getSort))
                .collect(Collectors.toList());
        List<SalaryBillFieldsDO> salaryBillFieldsDOList1 = new ArrayList<>();
        SalaryBillSendDO salaryBillSendDO = findByTableId(salaryBillDO.getTableId(), siteId);
        boolean showEmptyValue = Objects.nonNull(salaryBillSendDO) ? salaryBillSendDO.getShowEmptyValue() : true;
        if (!CollectionUtils.isEmpty(salaryBillFieldsDOList)) {
            for (SalaryBillFieldsDO salaryBillFieldsDO : salaryBillFieldsDOList) {
                boolean flag = (!showEmptyValue) &&
                        (salaryBillFieldsDO.getFieldValue() == null || "0".equals(salaryBillFieldsDO.getFieldValue()));
                if (!flag) {
                    if ("基本工资".equals(salaryBillFieldsDO.getFieldName())) {
                        try {
                            salaryBillDO.setSalaryBasic(new BigDecimal(salaryBillFieldsDO.getFieldValue()));
                        } catch (Exception e) {
                            throw new ParamException("基本工资有误");
                        }
                    } else {
                        salaryBillFieldsDOList1.add(salaryBillFieldsDO);
                    }
                }
            }
        }
        List<SalaryBillFieldsDO> collect = salaryBillFieldsDOList1.stream()
                .sorted(Comparator.comparing(SalaryBillFieldsDO::getSort))
                .collect(Collectors.toList());
        SalaryBillVO salaryBillVO = salaryBillDO.to(SalaryBillVO.class);
        salaryBillVO.setShowEmptyValue(showEmptyValue);
        salaryBillVO.setSalaryBillFieldsDOList(collect);

        // 工资条发放自动确认时间计算剩余时间
        Date now = DateKit.getToday();
        Example example = new Example(SalaryBillSendRelDO.class);
        example.and()
                .andEqualTo("billId", salaryBillDO.getId())
                .andEqualTo("valid", true);
        List<SalaryBillSendRelDO> salaryBillSendRelDOList = salaryBillSendRelDAO.selectByExample(example);
        if (!CollectionUtils.isEmpty(salaryBillSendRelDOList)) {
//            salaryBillSendRelDOList.sort((a,b) -> DateUtil.parse(a.getAutoCheckTime().toString()).getTime() - DateUtil.parse(b.getAutoCheckTime().toString()).getTime() >= 0 ? -1 : 1);
            salaryBillSendRelDOList.sort((a1, a2) -> a2.getAutoCheckTime().compareTo(a1.getAutoCheckTime()));
//            salaryBillSendRelDOList = salaryBillSendRelDOList.stream().sorted(Comparator.comparing(item -> item.getAutoCheckTime(), Comparator.nullsLast(Date::compareTo))).collect(Collectors.toList());
            Date autoCheckTime = salaryBillSendRelDOList.get(0).getAutoCheckTime();
            // 自动确认时间 大于等于 当前时间
            if (autoCheckTime.compareTo(now) >= 0) {
                salaryBillVO.setAutoCheckDiffStr(DateUtils.getDateDiffStr(autoCheckTime, now));
            }
        }

        return salaryBillVO;
    }

    /**
     * 根据tableId查找发放记录
     *
     * @param tableId 表id
     * @param siteId  站点id
     * @return 发放记录
     */
    private SalaryBillSendDO findByTableId(String tableId, String siteId) {
        Example example = new Example(SalaryBillSendDO.class);
        example.and()
                .andEqualTo("tableId", tableId)
                .andEqualTo("siteId", siteId);
        List<SalaryBillSendDO> salaryBillSendList = salaryBillSendDAO.selectByExample(example);
        if (CollectionUtils.isEmpty(salaryBillSendList)) {
            return null;
        }
        return salaryBillSendList.get(0);
    }

    /**
     * 根据tableId查找发放记录
     *
     * @param Id     表id
     * @param siteId 站点id
     * @return 发放记录
     */
    private SalaryBillDO findTableId(String Id, String siteId) {
        Example example = new Example(SalaryBillDO.class);
        example.and()
                .andEqualTo("id", Id)
                .andEqualTo("siteId", siteId);
        List<SalaryBillDO> salaryBillDOList = salaryBillDAO.selectByExample(example);
        if (CollectionUtils.isEmpty(salaryBillDOList)) {
            return null;
        }
        return salaryBillDOList.get(0);
    }
}




